FrameLib  0.1
Arbitrarily timed and sized frame-based DSP
FrameLib_Threading.h
Go to the documentation of this file.
1 
2 #ifndef FrameLib_THREADING_H
3 #define FrameLib_THREADING_H
4 
5 #ifdef __APPLE__
6 
7 #include <libkern/OSAtomic.h>
8 #include <pthread.h>
9 #include <mach/semaphore.h>
10 #include <mach/task.h>
11 
12 // Mac OS specific definitions
13 
14 typedef volatile int32_t Atomic32;
15 
16 static inline int32_t increment32(Atomic32 *a) { return OSAtomicIncrement32Barrier(a); }
17 static inline int32_t decrement32(Atomic32 *a) { return OSAtomicDecrement32Barrier(a); }
18 static inline int32_t add32(Atomic32 *a, int32_t b) { return OSAtomicAdd32Barrier(b, a); }
19 static inline bool compareAndSwap32(Atomic32 *loc, int32_t comp, int32_t exch) { return OSAtomicCompareAndSwap32Barrier(comp, exch, loc); }
20 
21 typedef void * volatile AtomicPtr;
22 
23 static inline bool compareAndSwapPtr(AtomicPtr *loc, void *comp, void *exch) { return OSAtomicCompareAndSwapPtrBarrier(comp, exch, loc); }
24 static inline void *swapPtr(AtomicPtr *loc, void *swap)
25 {
26  void *ptr = *loc;
27 
28  while (!compareAndSwapPtr(loc, ptr, swap))
29  ptr = *loc;
30 
31  return ptr;
32 }
33 
34 typedef pthread_t OSThreadType;
35 typedef semaphore_t OSSemaphoreType;
36 typedef void *OSThreadFunctionType(void *arg);
37 
38 #else
39 
40 // Windows OS specific definitions
41 
42 #include <windows.h>
43 
44 typedef volatile long Atomic32;
45 
46 static inline long increment32(Atomic32 *a) { return InterlockedIncrement(a); }
47 static inline long decrement32(Atomic32 *a) { return InterlockedDecrement(a); }
48 static inline long add32(Atomic32 *a, long b) { return InterlockedAdd(a, b); }
49 static inline bool compareAndSwap32(Atomic32 *loc, long comp, long exch) { return InterlockedCompareExchange(loc, exch, comp) == comp; }
50 
51 typedef volatile PVOID AtomicPtr;
52 
53 static inline bool compareAndSwapPtr(AtomicPtr *loc, void *comp, void *exch) { return InterlockedCompareExchangePointer(loc, exch, comp) == comp; }
54 static inline void *swapPtr(AtomicPtr *loc, void *swap) { return InterlockedExchangePointer(loc, swap); }
55 
56 typedef HANDLE OSThreadType;
57 typedef HANDLE OSSemaphoreType;
58 typedef DWORD WINAPI OSThreadFunctionType(LPVOID arg);
59 
60 #endif
61 
62 // An atomic 32 bit integer
63 
65 {
66 
67 public:
68 
69  FrameLib_Atomic32(int32_t value) : mValue(value) {}
70  FrameLib_Atomic32() : mValue(0) {}
71 
72  bool compareAndSwap(int32_t comparand, int32_t exchange) { return compareAndSwap32(&mValue, comparand, exchange); }
73 
74  int32_t operator = (const int32_t value)
75  {
76  mValue = value;
77  return value;
78  }
79 
80  int32_t operator += (const int32_t& a) { return add32(&mValue, a); }
81 
82  int32_t operator ++ () { return increment32(&mValue); }
83  int32_t operator ++ (int) { return operator++() - 1; }
84  int32_t operator -- () { return decrement32(&mValue); }
85  int32_t operator -- (int) { return operator--() + 1; }
86 
87 private:
88 
89  // Deleted
90 
93 
94  Atomic32 mValue;
95 };
96 
97 
98 // An atomic pointer
99 
100 template <class T> class FrameLib_AtomicPtr
101 {
102 
103 public:
104 
105  FrameLib_AtomicPtr() { mValue = NULL; }
106 
107  bool compareAndSwap(T *comparand, T *exchange) { return compareAndSwapPtr(&mValue, comparand, exchange); }
108  T *swap(T *exchange) { return (T *) swapPtr(&mValue, exchange); }
109  T *clear() { return swap(NULL); }
110 
111 private:
112 
113  // Deleted
114 
117 
118  AtomicPtr mValue;
119 };
120 
121 
122 // A spinlock that can be locked, attempted or acquired
123 
125 {
126 
127 public:
128 
130  ~FrameLib_SpinLock() { acquire(); }
131 
132  bool attempt() { return mAtomicLock.compareAndSwap(0, 1); }
133  void acquire() { while(attempt() == false); }
134  void release() { mAtomicLock.compareAndSwap(1, 0); }
135 
136 private:
137 
138  // Deleted
139 
142 
143  FrameLib_Atomic32 mAtomicLock;
144 };
145 
146 
147 // A class for holding a lock using RAII
148 
150 {
151 
152 public:
153 
154  FrameLib_SpinLockHold(FrameLib_SpinLock *lock) : mLock(lock) { if (mLock) mLock->acquire(); }
155  ~FrameLib_SpinLockHold() { if (mLock) mLock->release(); }
156 
157  void destroy()
158  {
159  if (mLock)
160  mLock->release();
161  mLock = NULL;
162  }
163 
164 private:
165 
166  FrameLib_SpinLock *mLock;
167 };
168 
169 
170 // Lightweight joinable thread
171 
172 class Thread
173 {
174 
175  typedef void ThreadFunctionType(void *);
176 
177 public:
178 
179  enum PriorityLevel {kLowPriority, kMediumPriority, kHighPriority, kAudioPriority};
180 
181  Thread(PriorityLevel priority, ThreadFunctionType *threadFunction, void *arg)
182  : mInternal(NULL), mPriority(priority), mThreadFunction(threadFunction), mArg(arg), mValid(false)
183  {}
184 
185  ~Thread();
186 
187  void start();
188  void join();
189 
190 private:
191 
192  // Deleted
193 
194  Thread(const Thread&);
195  Thread& operator=(const Thread&);
196 
197  // threadStart is a quick OS-style wrapper to call the object which calls the relevant static function
198 
199  static OSThreadFunctionType threadStart;
200  void call() { mThreadFunction(mArg); }
201 
202  // Data
203 
204  OSThreadType mInternal;
205  PriorityLevel mPriority;
206  ThreadFunctionType *mThreadFunction;
207  void *mArg;
208  bool mValid;
209 };
210 
211 
212 // Semaphore (note that you should most likely close() before the destructor is called)
213 
215 {
216 
217 public:
218 
219  Semaphore(long maxCount);
220  ~Semaphore();
221 
222  void close();
223  void signal(long n);
224  bool wait();
225 
226 private:
227 
228  // Deleted
229 
230  Semaphore(const Semaphore&);
231  Semaphore& operator=(const Semaphore&);
232 
233  // Data
234 
235  OSSemaphoreType mInternal;
236  bool mValid;
237 };
238 
239 
240 // A thread that can be triggered from another thread but without any built-in mechanism to check progress
241 
243 {
244 
245 public:
246 
247  TriggerableThread(Thread::PriorityLevel priority) : mThread(priority, threadEntry, this), mSemaphore(1) {}
248  virtual ~TriggerableThread() {}
249 
250  // Start and join
251 
252  void start() { mThread.start(); }
253  void join();
254 
255  // Trigger the thread to do something
256 
257  void signal() { mSemaphore.signal(1); };
258 
259 private:
260 
261  // Deleted
262 
263  TriggerableThread(const Thread&);
265 
266  // threadEntry simply calls threadClassEntry which calls the task handler
267 
268  static void threadEntry(void *thread);
269  void threadClassEntry();
270 
271  // Override this and provide code for the thread's functionality
272 
273  virtual void doTask() = 0;
274 
275  // Data
276 
277  Thread mThread;
278  Semaphore mSemaphore;
279 };
280 
281 
282 // A thread to delegate tasks to, which can be then be checked for completion
283 
285 {
286 
287 public:
288 
289  DelegateThread(Thread::PriorityLevel priority) : mThread(priority, threadEntry, this), mSemaphore(1), mSignaled(false) {}
290  virtual ~DelegateThread() {}
291 
292  // Start and join
293 
294  void start() { mThread.start(); }
295  void join();
296 
297  // Signal the thread to do something if it is not busy (returns true if the thread was signalled, false if busy)
298 
299  bool signal();
300 
301  // Wait for thread's completion of a task - returns true first time after a signal / false for subsequent calls/the thread has not been signalled
302 
303  bool completed();
304 
305 private:
306 
307  // Deleted
308 
311 
312  // threadEntry simply calls threadClassEntry which calls the task handler
313 
314  static void threadEntry(void *thread);
315  void threadClassEntry();
316 
317  // Override this and provide code for the thread's functionality
318 
319  virtual void doTask() = 0;
320 
321  // Data
322 
323  Thread mThread;
324  Semaphore mSemaphore;
325 
326  bool mSignaled;
327  FrameLib_Atomic32 mFlag;
328 };
329 
330 #endif
HANDLE OSSemaphoreType
Definition: FrameLib_Threading.h:57
int32_t operator++()
Definition: FrameLib_Threading.h:82
T * swap(T *exchange)
Definition: FrameLib_Threading.h:108
Definition: FrameLib_Threading.h:64
Definition: FrameLib_Threading.h:100
Definition: FrameLib_Threading.h:124
void signal()
Definition: FrameLib_Threading.h:257
int32_t operator--()
Definition: FrameLib_Threading.h:84
void start()
Definition: FrameLib_Threading.h:294
void start()
Definition: FrameLib_Threading.h:252
bool compareAndSwap(T *comparand, T *exchange)
Definition: FrameLib_Threading.h:107
Definition: FrameLib_Threading.h:172
FrameLib_SpinLockHold(FrameLib_SpinLock *lock)
Definition: FrameLib_Threading.h:154
bool attempt()
Definition: FrameLib_Threading.h:132
TriggerableThread(Thread::PriorityLevel priority)
Definition: FrameLib_Threading.h:247
virtual ~DelegateThread()
Definition: FrameLib_Threading.h:290
~FrameLib_SpinLockHold()
Definition: FrameLib_Threading.h:155
DWORD WINAPI OSThreadFunctionType(LPVOID arg)
Definition: FrameLib_Threading.h:58
Definition: FrameLib_Threading.h:149
T * clear()
Definition: FrameLib_Threading.h:109
Definition: FrameLib_Threading.h:284
FrameLib_Atomic32(int32_t value)
Definition: FrameLib_Threading.h:69
bool compareAndSwap(int32_t comparand, int32_t exchange)
Definition: FrameLib_Threading.h:72
HANDLE OSThreadType
Definition: FrameLib_Threading.h:56
Definition: FrameLib_Threading.h:242
void release()
Definition: FrameLib_Threading.h:134
FrameLib_Atomic32()
Definition: FrameLib_Threading.h:70
Definition: FrameLib_Threading.h:214
virtual ~TriggerableThread()
Definition: FrameLib_Threading.h:248
volatile PVOID AtomicPtr
Definition: FrameLib_Threading.h:51
volatile long Atomic32
Definition: FrameLib_Threading.h:44
int32_t operator+=(const int32_t &a)
Definition: FrameLib_Threading.h:80
FrameLib_AtomicPtr()
Definition: FrameLib_Threading.h:105
int32_t operator=(const int32_t value)
Definition: FrameLib_Threading.h:74
FrameLib_SpinLock()
Definition: FrameLib_Threading.h:129
~FrameLib_SpinLock()
Definition: FrameLib_Threading.h:130
int32_t operator++(int)
Definition: FrameLib_Threading.h:83
void acquire()
Definition: FrameLib_Threading.h:133
int32_t operator--(int)
Definition: FrameLib_Threading.h:85
void destroy()
Definition: FrameLib_Threading.h:157
Thread(PriorityLevel priority, ThreadFunctionType *threadFunction, void *arg)
Definition: FrameLib_Threading.h:181
void start()
Definition: FrameLib_Threading.cpp:120
DelegateThread(Thread::PriorityLevel priority)
Definition: FrameLib_Threading.h:289
PriorityLevel
Definition: FrameLib_Threading.h:179